翻译|How to conditional create Object with es6

原文参见

在不同资源之间移动用户创建的数据,需要你检查字段是否有值存在.然后可以根据检查结果来构建输出结果. 使用 ES6的特征来做这件事情可以更为简洁.

自从 Sanity.io 发起 Syntax 开始,我就一直在修补 有关 CLIs,Express,Serverless函数方面的博客 RSS. 其中的任务包括解析和构建有很多字段和信息的复杂对象. 因为你要处理来自不同资源的用户数据,所以不能保证所有的字段都是可用的. 因为字段本身也是可选的.而且你也不想在 RSS XML或者 JSON FEED中输出没有值的标签.

很早之前,我的处理方法是在对象上使用新的键,像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function episodeParser(data) {
const { id,
title,
description,
optionalField,
anotherOptionalField
} = data
const parsedEpisode = { guid: id, title, summary: description }
if (optionalField) {
parsedEpisode.optionalField = optionalField
} else if (anotherOptionalField) {
parsedEpisode.anotherOptionalField = anotherOptionalField
}
// and so on
return parsedEpisode
}

这个方法并不是太优雅(但是还是能工作的),如果你有很多字段,最终会栽在大量的if声明当中. 循环对象键也是类似的归宿. 这意味着代码盘根错节,对于数据对象也不会有什么好的感受.

然而,新的 ES6语法可以改变这些问题. 我发现可以像下面这样来改写代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function episodeParser({
id,
title,
description = 'No summary',
optionalField,
anotherOptionalField
}) {
return {
guid: id,
title,
summary: description,
...(optionalField && {optionalField}),
...(anotherOptionalField && {anotherOptionalField})
}
}

这个函数有很多属性.第一个参数是参数对象解构,如果在一个函数中有很多参数,对象解构就是一个很好的模式.可以代替下面的模式:

1
2
3
4
5
function episodePraser(data){
const id=data.id
const title=data.title
//等等
}

可以改写为:

1
2
3
function({id,title}){
//等等
}

这是一个很好的方法,可以避免在函数中出现很多的参数.也要注意对象解构中的description='No Summary'部分. 这是默认的使用的参数. 意思是如果description没有定义,可以使用字符串No Summary 作为替补.

第二个是三个小点 展开语法(…) .如果条件为真(&&的用法),就可以解包对象:

1
2
3
4
5
6
7
8
9
{
id: 'some-id',
...(true && { optionalField: 'something'})
}
// is the same as
{
id: 'some-id',
optionalField: 'someting'
}

最终得到的是一个简洁明了的函数,也很容易测试.一个重要的警告是在使用&&操作符时,数字0是被当做 false的.所以需要注意数据类型.

如果函数用于实战,结果如下

1
2
3
4
5
6
7
8
const data = { 
id: 1,
title: 'An episode',
description: 'An episode summary',
anotherOptionalField: 'some data'
}
episodeParser(data)
//> { guid: 1, title: 'An episode', summary: 'An episode summary', anotherOptionalField: 'some data' }